package com.ufgov.smartclient.component.table;

import java.awt.Component;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * 功能说明：
 * 对TableColumn进行分组，向UI提供数据模型，以便View层进行绘制
 * 分组方式采用索引方式，如：0到3列分为一组，标题为基本情况
 * 特殊说明：目前支持双层表头，如需更多层需进行二次开发
 * @author 刘永伟
 * @version 1.0
 * 创建时间：2007-7-9
 */
public class ColumnGroup {

  protected List<Object> identifiers = new ArrayList<Object>();

  /**
   * 多表头显示标题
   */
  protected Object headerValue = "";

  /**
   * 表头渲染器
   */
  protected TableCellRenderer headerRenderer = null;

  /**
   * 表头对象
   */
  protected JGroupableTableHeader header = null;

  protected ColumnGroup(JGroupableTableHeader header, Object headerValue,
    Object[] identifiers) throws IllegalArgumentException {

    this.identifiers.addAll(Arrays.asList(identifiers));
    this.header = header;
    this.headerValue = headerValue;
  }

  /**
   * 返回渲染器
   * @return TableCellRenderer
   */
  public TableCellRenderer getHeaderRenderer() {
    if (headerRenderer == null)
      headerRenderer = createDefaultTableCellRenderer();
    return headerRenderer;
  }

  public void setHeaderRenderer(TableCellRenderer headerRenderer) {
    this.headerRenderer = headerRenderer;
  }

  protected TableCellRenderer createDefaultTableCellRenderer() {
    final TableCellRenderer delegate = header.getDefaultRenderer();
    return new TableCellRenderer() {

      @Override
      public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
        Component comp = delegate.getTableCellRendererComponent(table, value,
          isSelected, hasFocus, row, column);
        if (comp instanceof JLabel) {
          ((JLabel) comp).setIcon(null);
        }
        return comp;
      }
    };
  }

  /**
   * 返回组标题
   * @return Object
   */
  public Object getHeaderValue() {
    return headerValue;
  }

  /**
   * 返回所包含的TableColumn列表
   * @return List
   */
  public List<TableColumn> getTableColumns() {
    List<TableColumn> result = new Vector<TableColumn>();
    for (Object id : identifiers) {
      result.add(header.getTable().getColumn(id));
    }
    return result;
  }

  /**
   * 设置组显示的标题
   * @param value
   */
  public void setHeaderValue(Object value) {
    this.headerValue = value;
  }

  /**
   * @param column
   * @return 组是否包含指定的列
   */
  public boolean isInclude(TableColumn column) {
    return identifiers.indexOf(column.getIdentifier()) > -1;
  }

  /**
   * @return 表头绘制的区域列表
   */
  public Map<Rectangle, List<Object>> getHeadRects() {
    int hOffset = 0;
    if (header.getHeaderComponent() != null
      && header.getHeaderComponent().isVisible()) {
      hOffset = header.getHeaderComponent().getPreferredSize().height;
    }
    Map<Rectangle, List<Object>> rectMap = new LinkedHashMap<Rectangle, List<Object>>();
    TableColumnModel columnModel = header.getColumnModel();
    Rectangle rect = new Rectangle(-1, 0, 0, 0);
    List<Object> idList = new ArrayList<Object>();
    for (int i = 0; i < columnModel.getColumnCount(); i++) {
      TableColumn column = columnModel.getColumn(i);
      if (isInclude(column)) {
        idList.add(column.getIdentifier());
        Rectangle headerRect = header.getHeaderRect(i);
        rect.width += column.getPreferredWidth();
        rect.height = Math.max(rect.height, headerRect.height);
        if (rect.x == -1)
          rect.x = headerRect.x;
        if (i == columnModel.getColumnCount() - 1
          || !isInclude(columnModel.getColumn(i + 1))) {
          rect.y = hOffset;
          rectMap.put(rect, idList);
          idList = new ArrayList<Object>();
          rect = new Rectangle(-1, 0, 0, 0);
        }
      }
    }
    return rectMap;
  }
}
